﻿using DataDefinition;
using LLTreeManagementApplication.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

namespace LLTreeManagementApplication.Export
{
    public class Action
    {
        public string NodeName { get; set; }
        public string NodePath { get; set; }
        public string NodeId { get; set; }
        public string SourceNodePath { get; set; }
        public SharePointType Type { get; set; }
        public bool Exclude { get; set; }
        public ActionType ActionType { get; set; }
    }

    public enum ActionType
    {
        Undefined = 0,
        Move = 1,
        Exclude = 2,
        Insert = 3,
        Remove = 4,
        Rename = 5,
        TemplateChange = 6,
        Convert = 7
    }

    public delegate void ExportHandlerInformationUpdate(int actionItems);

    class ExportHandler
    {
        #region Membervariables
        List<Action> _actionList = new List<Action>();
        #endregion

        #region Propoerties
        public List<Action> ActionList { get { return _actionList; } }
        #endregion

        #region Events

        public ExportHandlerInformationUpdate ExportHandlerInformationUpdate;

        #endregion

        #region Action Methods
        public void MoveAction(TreeNode source, TreeNode target)
        {
            DataNode data = source.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Move, Type = data.SharePointType, NodeId = data.SourceId, NodeName = data.Title, SourceNodePath = GetPathToRoot(source), NodePath = GetPathToRoot(target) };
            ActionList.Add(action);
            Console.WriteLine(string.Format("Drop Source from [{0}] to [{1}]", GetPathToRoot(source), GetPathToRoot(target)));
            SendHandlerInformation();
        }

        public void ExcludeAction(TreeNode node, bool exclude)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Exclude, Type = data.SharePointType, NodeId = data.SourceId, NodeName = data.Title, NodePath = GetPathToRoot(node), Exclude = exclude };
            ActionList.Add(action);
            Console.WriteLine(string.Format("Exclude node [{0}] is {1}", GetPathToRoot(node), exclude));
            SendHandlerInformation();
        }

        public void InsertAction(TreeNode node)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Insert, Type = data.SharePointType, NodeName = data.Title, NodePath = GetPathToRoot(node)};
            ActionList.Add(action);

            Console.WriteLine(string.Format("New Node inserted [{0}]", GetPathToRoot(node)));
            SendHandlerInformation();
        }

        public void RemoveAction(TreeNode node)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Remove, Type = data.SharePointType, NodeName = data.Title, NodePath = GetPathToRoot(node) };
            ActionList.Add(action);
            Console.WriteLine(string.Format("Node removed [{0}]", GetPathToRoot(node)));
            SendHandlerInformation();
        }

        public void RenameAction(TreeNode node, string newName)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Rename, Type = data.SharePointType, NodeName = newName, NodePath = GetPathToRoot(node) };
            ActionList.Add(action);
            Console.WriteLine(string.Format("Node renamed [{0}] to [{1}]", GetPathToRoot(node), newName));
            SendHandlerInformation();
        }

        public void TemplateChangeAction(TreeNode node)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.TemplateChange, Type = data.SharePointType, NodeName = data.Title, NodePath = GetPathToRoot(node) };
            ActionList.Add(action);
            Console.WriteLine(string.Format("Node template changed [{0}], template [{1}]", GetPathToRoot(node), "Template xy"));
            SendHandlerInformation();
        }

        public void ConvertNode(TreeNode node, SharePointType newType)
        {
            DataNode data = node.Tag as DataNode;

            var action = new Action() { ActionType = Export.ActionType.Convert, Type = newType, NodeName = data.Title, NodePath = GetPathToRoot(node) };
            ActionList.Add(action);

            Console.WriteLine(string.Format("Convert Node [{0}] to [{1}]", GetPathToRoot(node), newType.ToString("G")));
            SendHandlerInformation();
        }
        #endregion

        #region Private Methods
        string GetPathToRoot(TreeNode node)
        {
            string path = "";
            var runner = node;
            while (runner != null)
            {
                path = string.Format("{0}/{1}", runner.Text, path);
                runner = runner.Parent;
            }
            return path;
        }

        void SendHandlerInformation()
        {
            if (ExportHandlerInformationUpdate != null)
            {
                ExportHandlerInformationUpdate(_actionList.Count);
            }
        }

        #endregion

        #region Load/Save Methods
        public void LoadXml(Stream stream)
        {          
            XmlSerializer serializer = new XmlSerializer(typeof(List<Action>));
            var other = (List<Action>)(serializer.Deserialize(stream));
             _actionList.Clear();
             _actionList.AddRange(other);
        }

        public StringBuilder Save()
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = new UnicodeEncoding(false, false);
            settings.Indent = true;
            settings.OmitXmlDeclaration = true;

            var serializer = new XmlSerializer(typeof(List<Action>));
            StringBuilder sb = new StringBuilder();
            using (XmlWriter writer = XmlWriter.Create(sb, settings))
            {
                serializer.Serialize(writer, _actionList);
            }
            return sb;
        }
        #endregion

        #region ResetActions
        public void ResetActions()
        {
            _actionList.Clear();
        }
        #endregion

        #region ExportMethods
        public void SaveAsCsv(string filePath)
        {
            string format = "{0};{1};{2};{3};{4};{5};{6}";
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(string.Format(format, "ActionType","NodeId","NodeName","NodePath","SourceNodePath","Type","Exclude"));

            foreach (var action in _actionList)
            {
                sb.AppendLine(string.Format(format, action.ActionType, action.NodeId, action.NodeName, action.NodePath, action.SourceNodePath, action.Type, action.Exclude));
            }

            File.WriteAllText(filePath, sb.ToString()); 
        }
        #endregion
    }
}
